#include "CustomModule.h"
#include "vtkSlicerApplication.h"
#include "vtkSlicerApplicationGUI.h"
#include "MyToolBar.h"
#include "CustomMenu.h"
#include "TestGUI.h"
#define MAKE_CUSTOM_LIB
#include "CustomModuleConfig.h"
#include "EndoscopeLogic.h"
#include "EndoscopeRenderWidget.h"
#include "vtkKWTkUtilities.h"
#include <vtktclutil.h>
#include "CustomModuleTCLInit.h"
#include "vtkVersion.h"
#define VTK_TCL_TO_STRING(x) VTK_TCL_TO_STRING0(x)
#define VTK_TCL_TO_STRING0(x) #x
CustomModule * CustomModule::OnlyOneInstance = NULL;

CustomModule *CustomModule::GetInstance()
{
	if (OnlyOneInstance != NULL)
		return OnlyOneInstance;
	else
	{
		OnlyOneInstance = new CustomModule;
		return OnlyOneInstance;
	}
}
CustomModule::CustomModule(void)
{
	Application = NULL;
	ApplicationLogic = NULL;
	MRMLSene = NULL;
	ESLogic = NULL;
	TclInterp = NULL;
}

CustomModule::~CustomModule(void)
{
	if (this->MyToolbar != NULL)
	{
		this->MyToolbar->Delete();
	}
	if (this->MyMenu != NULL)
	{
		this->MyMenu->Delete();
	}
	if (this->Endoscopegui != NULL)
	{
		this->Endoscopegui->Delete();
	}
	if (this->ESLogic != NULL)
	{
		this->ESLogic->Delete();
	}
	SetApplication(NULL);
	SetApplicationLogic(NULL);
	SetMRMLSene(NULL);
}

void CustomModule::MainGUIInitialize(void)
{
	if (this->Application != NULL)
	{
		vtkSlicerApplicationGUI *appGUI = this->Application->GetApplicationGUI();
		this->MyMenu = CustomMenu::New();
		MyMenu->SetApplication(this->Application);
		MyMenu->BuildGUI();
		MyMenu->SetAndObserveMRMLScene(this->MRMLSene);
		MyToolbar = CustomToolBar::New();
		MyToolbar->SetApplication(this->Application);
		MyToolbar->BuildGUI();
	}
}

void CustomClass_Init(Tcl_Interp * tclInterp)
{
	vtkTclCreateNew(tclInterp,(char *)("vtkEndoscopeRenderWidget"), EndoscopeRenderWidgetNewCommand,
		EndoscopeRenderWidgetCommand);
	vtkTclCreateNew(tclInterp,(char *)("EndoscopeLogic"), EndoscopeLogicNewCommand,
		EndoscopeLogicCommand);
	vtkTclCreateNew(tclInterp,(char *)("vtkVirtualDisplayWidget"), vtkVirtualDisplayWidgetNewCommand,
		vtkVirtualDisplayWidgetCommand);

	char pkgName[]="Endoscope";
	char pkgVers[]=VTK_TCL_TO_STRING(VTK_MAJOR_VERSION) "." VTK_TCL_TO_STRING(VTK_MINOR_VERSION);
	Tcl_PkgProvide(tclInterp, pkgName, pkgVers);
}
void CustomModule::InitializeModules(void)
{
	//
	// Initialize our Tcl library (i.e. our classes wrapped in Tcl)
	//
	CustomClass_Init(TclInterp);

	if (this->Application != NULL 
		&& this->ApplicationLogic != NULL
		&& this->MRMLSene != NULL)
	{
		// Endoscope GUI
		this->Application->SplashMessage( "Initializing Endoscope Module...");
		vtkSlicerApplicationGUI * appGUI = this->Application->GetApplicationGUI();
		this->Endoscopegui = EndoscopeGUI::New ( );
		this->ESLogic = EndoscopeLogic::New();
		//this->ESLogic->AddObserver(vtkCommand::UserEvent, this->Endoscopegui->GetLogicCallbackCommand());
		//this->Application->Script("set MRMLScene %s",  vtkKWTkUtilities::GetTclNameFromPointer(Application, this->MRMLSene));
		this->ESLogic->SetApplication(this->Application);
		this->ESLogic->SetModuleGUI(this->Endoscopegui);
		this->ESLogic->SetAndObserveMRMLScene(this->MRMLSene);
		this->Endoscopegui->SetAndObserveESLogic(this->ESLogic);
		this->Endoscopegui->SetApplication ( this->Application );
		this->Endoscopegui->SetApplicationGUI ( appGUI );
		this->Endoscopegui->SetAndObserveApplicationLogic (  this->ApplicationLogic );
		vtkIntArray *events = vtkIntArray::New();
		events->InsertNextValue(vtkMRMLScene::SceneCloseEvent);
		events->InsertNextValue(vtkMRMLScene::NewSceneEvent);
		events->InsertNextValue(vtkMRMLScene::NodeAddedEvent);
		events->InsertNextValue(vtkMRMLScene::NodeRemovedEvent);
		events->InsertNextValue(vtkCommand::ModifiedEvent);
		this->Endoscopegui->SetAndObserveMRMLSceneEvents(this->MRMLSene, events);
		events->Delete();
		this->Endoscopegui->SetGUIName( "Endoscope" );
		this->Endoscopegui->GetUIPanel()->SetName ( this->Endoscopegui->GetGUIName ( ) );
		this->Endoscopegui->GetUIPanel()->SetUserInterfaceManager (appGUI->GetMainSlicerWindow()->GetMainUserInterfaceManager ( ) );
		this->Endoscopegui->GetUIPanel()->Create ( );    
		this->Application->AddModuleGUI (this->Endoscopegui);
	}
}


int InitializeCustomModule (Tcl_Interp * tcl_Interp, vtkSlicerApplication *slicerApp, vtkSlicerApplicationLogic * appLogic, vtkMRMLScene * scene)
{
	CustomModule * CM = CustomModule::GetInstance();
	CM->SetTclInterp(tcl_Interp);
	CM->SetApplication(slicerApp);
	CM->SetApplicationLogic(appLogic);
	CM->SetMRMLSene(scene);
	CM->MainGUIInitialize();
	CM->InitializeModules();
	return 0;
}

void FinalizeCustomModule ()
{
	CustomModule::GetInstance()->Delete();
}